/*
 * DXManager.cpp
 *
 *  Created on: Feb 2, 2010
 *      Author: dcrown
 */


#include <d3d9.h>
#include <d3dx9.h>
#include <windows.h>
#include <map>
#include <utility>
#include <string>

#include "DXManager.h"
#include "..\Systems\Logger.h"
#include "Sprite.h"

using namespace std;

const int TEST_IMG_WIDTH = 96;
const int TEST_IMG_HEIGHT = 96;

//----------------------------------------------------------------------------------------------------------------------------
// Creation and Initialization
//----------------------------------------------------------------------------------------------------------------------------
void DXManager::Clear()
{
	LPDIRECT3D9 gd3dObject = NULL;
	LPDIRECT3DDEVICE9 gd3dDevice = NULL;
}

bool DXManager::Create(HWND hwnd)
{
	//create D3DObject
	if ((d3d = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
	{
		//if this pointer is null, D3D might not be initialized; fatal error
		Logger::getInstance().LOG(Logger::FATAL, "Failed to create D3D Object");
		return false;
	}

	//build/zeroize presentation parameters structure
	D3DPRESENT_PARAMETERS presParams;
	ZeroMemory(&presParams, sizeof(presParams));

	//fill in typical values for windowed mode
	presParams.Windowed = true;
	presParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
	presParams.BackBufferFormat = D3DFMT_UNKNOWN;
	presParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;

	//create D3D Device
	if (FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,
			&presParams, &device)))
	{
		Logger::getInstance().LOG(Logger::FATAL, "Failed to create D3D Device");
		return false;
	}
/*this belongs in resource manager
	//create the "missing" texture to show in place of textures we can't find
	if (LoadTexture(MISSING_TEXT_LOC, MISSING_TEXT_ID))
	{
		missingText = GetTexture(MISSING_TEXT_ID);
	}*/

	Logger::getInstance().LOG(Logger::DEBUG, "DXManager Created");
	return true;
}

//----------------------------------------------------------------------------------------------------------------------------
// Load Objects
//----------------------------------------------------------------------------------------------------------------------------
bool DXManager::LoadTexture(const char* filename, LPDIRECT3DTEXTURE9* texture, int width, int height)
{
	//texture not yet created
	if (FAILED(D3DXCreateTextureFromFileEx(device, filename, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT, 0,
			D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture)))
	{
		Logger::getInstance().LOG(Logger::RECOVERABLE, "Could not create texture");
		return false;
	}

	return true;
}

bool DXManager::LoadSprite(LPD3DXSPRITE* sprite)
{
	//create sprite
	if (FAILED(D3DXCreateSprite(device, sprite)))
	{
		Logger::getInstance().LOG(Logger::FATAL, "Could not create sprite");
		return false;
	}

	return true;
}
/*
bool DXManager::LoadTexturedSprite(const char* filename, string spriteId, string textId, int width, int height)
{
	//make sure we haven't created it yet
	Sprite* s = GetSprite(spriteId);
	if (s == NULL)
	{
		//try to load the texture first (doesn't matter if this fails here, we just show missingtext)
		LoadTexture(filename, textId, width, height);

		//then create the sprite
		s = new Sprite;
		if (s->Create(device, textId, width, height, NULL))
		{
			//successful
			spriteMap.insert(pair<string, Sprite*>(spriteId, s));
			return true;
		}
		else
		{
			Logger::getInstance().LOG(Logger::FATAL, "Could not create sprite");
			return false;
		}
	}
	else
	{
		//sprite already created
		return true;
	}
}
*/
//----------------------------------------------------------------------------------------------------------------------------
// Game Loop
//----------------------------------------------------------------------------------------------------------------------------
/*
void DXManager::Update()
{
	map<string, LPD3DXSPRITE*>::iterator iter;
	map<string, LPD3DXSPRITE*>::iterator begin = spriteMap.begin();
	map<string, LPD3DXSPRITE*>::iterator end = spriteMap.end();

	for (iter = begin; iter != end; ++iter)
	{
		(*iter).second->Update();
	}
}*/

//----------------------------------------------------------------------------------------------------------------------------
// Draw Objects
//----------------------------------------------------------------------------------------------------------------------------

bool DXManager::BeginRender()
{
	//clear the target buffer
	if (FAILED(device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,255,0), 1.0, 0)))
	{
		Logger::getInstance().LOG(Logger::FATAL, "Could not clear target buffer");
		return false;
	}

	//begin rendering the scene
	if (FAILED(device->BeginScene()))
	{
		Logger::getInstance().LOG(Logger::FATAL, "Could not begin scene");
		return false;
	}
}

bool DXManager::EndRender()
{
	//complete rendering the scene
	if (FAILED(device->EndScene()))
	{
		Logger::getInstance().LOG(Logger::FATAL, "Could not end scene");
		return false;
	}

	//present buffer to entire screen
	if (FAILED(device->Present(NULL, NULL, NULL, NULL)))
	{
		Logger::getInstance().LOG(Logger::FATAL, "Could not present scene");
		return false;
	}
}
//----------------------------------------------------------------------------------------------------------------------------
// Manipulate Objects
//----------------------------------------------------------------------------------------------------------------------------
/*
bool DXManager::ScaleSprite(string id, float x, float y)
{
	Sprite* s = GetSprite(id);

	if (s != NULL)
	{
		s->Scale(x, y);
		return true;
	}
	else
	{
		Logger::getInstance().LOG(Logger::FATAL, "Could not find sprite");
		return false;
	}
}

bool DXManager::TranslateSprite(string id, int x, int y)
{
	Sprite* s = GetSprite(id);

	if (s != NULL)
	{
		s->TranslateOriginal(x, y);
		return true;
	}
	else
	{
		Logger::getInstance().LOG(Logger::RECOVERABLE, "Could not find sprite");
		return false;
	}
}

bool DXManager::RotateSprite(string id, float rads)
{
	Sprite* s = GetSprite(id);

	if (s != NULL)
	{
		s->Rotate(rads);
		return true;
	}
	else
	{
		Logger::getInstance().LOG(Logger::RECOVERABLE, "Could not find sprite");
		return false;
	}
}

bool DXManager::UpdateSprite(string id)
{
	Sprite* s = GetSprite(id);

	if (s != NULL)
	{
		s->Update();
		return true;
	}
	else
	{
		Logger::getInstance().LOG(Logger::RECOVERABLE, "Could not find sprite");
		return false;
	}
}*/

void DXManager::ApplyTransform(LPD3DXSPRITE* sprite, D3DXVECTOR2* scalingCenter, float scalingRotation, D3DXVECTOR2* scale,
		D3DXVECTOR2* rotCenter, float rotation, D3DXVECTOR2* translation)
{
	D3DXMATRIX fullTransform;
	// out, scaling centre, scaling rotation, scaling, rotation centre, rotation, translation
	D3DXMatrixTransformation2D(&fullTransform, scalingCenter, scalingRotation, scale, rotCenter, rotation, translation);
	(*sprite)->SetTransform(&fullTransform);
}

void DXManager::Draw(LPD3DXSPRITE sprite, LPDIRECT3DTEXTURE9 texture, RECT* r)
{
	//all sprites have alphablending on
	sprite->Begin(D3DXSPRITE_ALPHABLEND);
	sprite->Draw(texture,r,NULL,NULL,0xFFFFFFFF);
	sprite->End();
}

//----------------------------------------------------------------------------------------------------------------------------
// Access Objects
//----------------------------------------------------------------------------------------------------------------------------
/*Sprite* DXManager::GetSprite(string id)
{
	Sprite* returnVal;

	map<string, Sprite*>::iterator iter;
	iter = spriteMap.find(id);

	if (iter == spriteMap.end())
	{
		returnVal = NULL;
	}
	else
	{
		returnVal = (*iter).second;
	}

	return returnVal;
}

LPDIRECT3DTEXTURE9 DXManager::GetTexture(string id)
{
	LPDIRECT3DTEXTURE9 returnVal;

	map<string, LPDIRECT3DTEXTURE9>::iterator iter;
	iter = textureMap.find(id);

	if (iter == textureMap.end())
	{
		returnVal = missingText;
	}
	else
	{
		returnVal = (*iter).second;
	}

	return returnVal;
}
*/
